====== Navigation im Fragebogen ======

Üblicherweise starten Teilnehmer auf der ersten Seite und füllen den Fragebogen dann sequenziell aus. Mitunter wird der Ablauf durch ein ''[[:de:create:functions:setpageorder]]'' oder ''[[:de:create:functions:gotopage]]'' verändert, aber auch dann folgen die Teilnehmer dem vom Projektleiter vorgegeben Ablauf.

Diese Anleitung beschreibt, wie man ein Menü bzw. eine Navigation im Fragebogen ergänzt, sodass Teilnehmer nach Belieben zwischen den Seiten/Abschnitten springen können. Dies ist vor allem dann sinnvoll, wenn man ein Formular in SoSci Survey zur Abfrage von Informationen einsetzt (s. auch [[:de:create:mix-forms]]).

{{:de:create:scr.navigation.result1.png?nolink|Beispiel für ein Navigationsmenü im Fragebogen}}


===== Grundlagen =====

Im ersten Schritt werden unter **Fragebogen zusammenstellen** [[:de:create:pageid|Seitenkennungen]] für alle Seiten eingetragen, zu denen der Teilnehmer springen kann. Der Titel der Seite wird als //Notiz// eingetragen.

{{:de:create:scr.navigation.pageid.png?nolink|Seitenkennung und Notiz eintragen}}

Die eigentlichen Navigationsknöpfe werden von der Funktion ''[[:de:create:functions:buttontopage]]'' erzeugt. Diese Funktion erzeugt HTML-Code, den man mittels ''[[:de:create:functions:html]]'' in der Fragebogen-Seite einbinden kann. Mit folgendem PHP-Code würde man auf einer Fragebogen-Seite Knöpfe zu unterschiedlichen Seiten anbieten.

<code php>
html(
  '<div>'.
  buttonToPage('start').
  buttonToPage('kontakt').
  buttonToPage('studium').
  buttonToPage('leistungen').
  buttonToPage('dokumente').
  buttonToPage('notizen').
  buttonToPage('abschicken').
  '</div>'
);
</code>

{{:de:create:scr.navigation.result2.png?nolink|Knöpfe zur Navigation zwischen unterschiedlichen Seiten}}

Der PHP-Code müsste nun auf jeder einzelnen Seite des Fragebogens (z.B. oben auf der Seite) eingefügt werden. Dies ist natürlich unpraktisch und erschwert nachträgliche Änderungen. Deshalb wird unter **Fragebogen zusammenstellen** im Karteireiter *PHP-Funktionen* eine neue Funktion definiert, welche sich um die Navigation und ggf. weitere Anpassungen kümmert.

<code php>
function navigation() {
    // Navigation
    html(
      '<div>'.
      buttonToPage('start').
      buttonToPage('kontakt').
      buttonToPage('studium').
      buttonToPage('leistungen').
      buttonToPage('dokumente').
      buttonToPage('notizen').
      buttonToPage('abschicken').
      '</div>'
    );
    // Beschriftung des Weiter-Knopfes
    option('nextbutton', 'Nächstes Formular');
}
</code>

Auf den einzelnen Seiten des Fragebogens muss dann nur noch ein PHP-Code eingebunden werden, welcher diese Funktion aufruft:

<code php>
navigation();
</code>


===== Darstellung anpassen =====

Mittels CSS lassen sich die Anordnung auf der Seite und die Darstellung der Knöpfe anpassen. Zunächst werden im HTML-Code einige Ergänzungen vorgenommen:

  * Im äußeren ''<div>''-Blockelement wird mit dem ''style''-Attribut ein grauer Rahmen (''border'') oben und unten ergänzt,
  * um die Knöpfe herum wird ein weiteres ''<div>'' Blockelement mit einer CSS-Klasse (im Beispiel "NavButtons") ergänzt. Die zusätzlich eingetragene Klasse ''s2flex'' erlaubt es, die gesamten Breite auszunutzen.
  * Zwischen den Knöpfen für "notizen" und "abschicken" wird ein leeres ''<div>''-Element ergänzt, um etwas Abstand zwischen den Knöpfen zu erzeugen.

<code php>
html(
  '<div style="border: 2px solid #CCCCCC; border-left: 0 none; border-right: 0 none; padding: 20px 0 12px 0; margin-bottom: 3em;">'.
  '<div class="s2flex NavButtons" style="flex-wrap: wrap; margin-right: -8px">'.NL.
  buttonToPage('start').
  buttonToPage('kontakt').
  buttonToPage('studium').
  buttonToPage('leistungen').
  buttonToPage('dokumente').
  buttonToPage('notizen').
  '<div style="width: 2em;"></div>'.
  buttonToPage('abschicken').
  '</div>'.
  '</div>'
);
</code>

Dazu passend werden im [[:de:create:layout|Fragebogen-Layout]] in der **HTMLVorlage** im ''<style>''-Bereich CSS-Anweisungen ergänzt:

<code css>
div.NavButtons button {
  border: 2px solid %color.4%;
  border-radius: 5px;
  padding: 7px 6px;
  margin-bottom: 8px;
  flex-grow: 1;
  margin-right: 8px;
}
div.NavButtons button.currentPage {
  background-color: %color.4%;
  color: white;
}
</code>

Der zweite Block (''button.currentPage'') sorgt dafür, dass der Navigationsknopf der aktuellen Seite farblich hervorgehoben wird. Der Befehl ''buttonToPage()'' belegt den Knopf, welcher auf die aktuelle Seite verweist, mit der CSS-Klasse ''currentPage''.


===== Ausfüllstatus anzeigen =====

Wenn die Reihenfolge zum Ausfüllen nicht vorgegeben ist, möchte man dem Teilnehmer vielleicht den aktuellen Bearbeitungstatus anzeigen -- also welche Seiten bereits vollständig ausgefüllt sind und welche noch nicht.

{{:de:create:scr.navigation.result3.png?nolink|Navigation mit Anzeige des Ausfüllstatus}}

Dafür werden im **Fragebogen-Layout** zunächst weitere CSS-Anweisungen ergänzt, welche hinter vollständigen Seiten einen grünen Haken und hinter unvollständigen Seiten ein rotes Kreuz anzeigen. Die beiden Symbole sind im UTF-8-Zeichensatz definiert und können (nebst Similies und anderen Symbolen) über ihre Zeichen-Codes (2713 und 274C) verwendet werden. Die aktuelle Seite soll kein Symbol zeigen.

<code css>
div.NavButtons button.complete:after { content: " \2713"; }
div.NavButtons button.incomplete:after { content: " \274C"; }
div.NavButtons button.currentPage:after { content: none; }
</code>

Ob die Seite vollständig ausgefüllt ist oder nicht, das muss der PHP-Code unter Zuhilfenahme von ''[[:de:create:functions:value]]'' oder ''[[:de:create:functions:getItems]]'' jeweils überprüfen. Die CSS-Klassen ''complete'' und ''incomplete'' können dann als vierter Parameter in der Funktion ''[[:de:create:functions:buttontopage]]'' angegeben werden. Der zweite und dritte Parameter bleibt mit ''NULL'' leer.

Der PHP-Code dafür wird in den *PHP-Funktionen* des Fragebogens abgespeichert und könnte wie folgt aussehen:

<code php>
function navigation() {
    // Completion check
    $cKontakt = (count(array_merge(
        checkItem('KD02', 'KD01_01'),
        checkQst('KD01', [2,3,4,5,6,8]),
        checkItem('KD03', 'KD01_07')
    )) === 0);
    
    $cStart = (
      (count(array_intersect(getItems('KD01', 'valid'), [2,3,4,5,6,8])) == 6) and
      (value('KD02') > 0) and
      ((value('KD03') > 0) or (value('KD03') == -2))
    );
    
    // Hier können weitere Überprüfungen für ...
    // "studium"    -> $cStudium
    // "leistungen" -> $cLeistungen
    // "dokumente"  -> $cDokumente
    // ... ergänzt werden.
    
    
    // Navigation
    html('<div style="border: 2px solid #CCCCCC; border-left: 0 none; border-right: 0 none; padding: 20px 0 12px 0; margin-bottom: 3em;">'.
      '<div class="s2flex NavButtons" style="flex-wrap: wrap; margin-right: -8px">'.NL.
      buttonToPage('start').
      buttonToPage('kontakt', NULL, NULL, ($cKontakt ? 'complete' : 'incomplete')).
      buttonToPage('studium', NULL, NULL, ($cStudium ? 'complete' : 'incomplete')).
      buttonToPage('leistungen', NULL, NULL, ($cLeistungen ? 'complete' : 'incomplete')).
      buttonToPage('dokumente', NULL, NULL, ($cDokumente ? 'complete' : 'incomplete')).
      buttonToPage('notizen').
      '<div style="width: 2em;"></div>'.
      buttonToPage('abschicken').
      '</div>'.
      '</div>'
    );
    option('nextbutton', 'Nächstes Formular');
}


function checkQst($qID, $items) {
  $fail = [];
  foreach ($items as $item) {
    $answer = value(id($qID, $item));
    if (($answer < -3) or ($answer === '')) {
      $text = preg_replace('/:.*/', '', getItemtext($qID, $item));
      $fail[] = $text;
    }
  }
  return $fail;
}

function checkItem($varIDs, $textID) {
  $fail = [];
  if (!is_array($varIDs)) {
    $varIDs = [$varIDs];
  }
  foreach ($varIDs as $varID) {
    $answer = value($varID);
    if (($answer < -3) or ($answer === '')) {
      $text = preg_replace('/:.*/', '', getItemtext($textID));
      $fail[] = $text;
      // Only one of them
      break;
    }
  }
  return $fail;
}
</code>

Für das Zuweisen der CSS-Klasse ''complete'' oder ''incomplete'' ist folgender Code-Schnipsel verantwortlich, der in variierter Form jeweils als vierter Parameter in der Funktion ''buttonToPage()'' eingetragen steht:

<code php>
    ($cKontakt ? 'complete' : 'incomplete')
</code>

Die Knöpfe für "start", "notizen" und "abschicken" erhalten in diesem Beispiel keine Statusanzeige.

Wie der PHP-Code zur Überprüfung der Vollständigkeit konkret aussieht, hängt vom Einzelfall ab. Die Funktionen ''checkQst()'' und ''checkItem()'' können hier hilfreich sein. Diese Funktionen sind außerdem so ausgelegt, dass sie eine Liste fehlender Angaben liefern. So lässt sich auf der Seite "abschicken" eine Übersicht anzeigen, was noch ausgefüllt werden muss.

Eventuell werden einzelne Überprüfungen auch komplizierter und müssen in separate Funktionen ausgelagert werden.

<code php>
    $cStudium = (count(checkStudium()) === 0);
    $cLeistungen = (count(checkECTS()) === 0);
    $cDokumente = (count(checkDocs()) === 0);
</code>